//
//  GKVideoPlayerManager.m
//  AVPlayerDemo
//
//  Created by YIDAOMAC on 2024/1/16.
//

#import "GKVideoPlayerManager.h"
#import "GKPlayable.h"
#import <AVKit/AVKit.h>
#import <VideoToolbox/VideoToolbox.h>
#import <KTVHTTPCache/KTVHTTPCache.h>

@interface GKVideoPlayerManager()

///
@property(nonatomic, strong) AVPlayer *player;

///当前播放的
@property(nonatomic, weak) id<GKPlayable> currentPlayable;

///
@property(nonatomic, strong) AVPlayerItemVideoOutput *videoOutput;

@end

@implementation GKVideoPlayerManager

+ (GKVideoPlayerManager *)manager
{
    static dispatch_once_t onceToken;
    static GKVideoPlayerManager *sharedManager = nil;
    dispatch_once(&onceToken, ^{
        sharedManager = [GKVideoPlayerManager new];
    });
    
    return sharedManager;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        AVPlayer *player = [AVPlayer new];
        [player addObserver:self forKeyPath:@"status" options:0 context:nil];
        player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
        player.allowsExternalPlayback = NO;
        player.muted = YES;
        self.player = player;
    }
    return self;
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if (!decelerate) {
        [self playIfEnabledWithScrollView:scrollView];
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self playIfEnabledWithScrollView:scrollView];
}

- (NSArray<UIView*>*)cellsFromScrollView:(UIScrollView*) scrollView
{
    if ([scrollView isKindOfClass:UITableView.class]) {
        return [(UITableView*)scrollView visibleCells];
    } else if ([scrollView isKindOfClass:UICollectionView.class]) {
        return [(UICollectionView*)scrollView visibleCells];
    }
    
    return nil;
}
 
- (void)playIfEnabledWithScrollView:(UIScrollView*) scrollView;
{
    NSArray *cells = [self cellsFromScrollView:scrollView];
    cells = [cells sortedArrayUsingComparator:^NSComparisonResult(UIView<GKPlayable> *playable1, UIView<GKPlayable> *playable2) {
        if (playable1.center.y < playable2.center.y) {
            return NSOrderedAscending;
        } else if (playable1.center.y == playable2.center.y) {
            return playable1.center.x < playable2.center.x ? NSOrderedAscending : NSOrderedDescending;
        }
        return NSOrderedDescending;
    }];
    Protocol *protocol = @protocol(GKPlayable);
    for (UIView<GKPlayable> *playable in cells) {
        if ([playable conformsToProtocol:protocol] && scrollView.contentOffset.y <= playable.frame.origin.y && playable.videoURL != nil) {
            [self playWithPlayable:playable];
            break;
        }
    }
}

- (void)setCurrentPlayable:(id<GKPlayable>)currentPlayable
{
    if (_currentPlayable != currentPlayable) {
        _currentPlayable.playing = NO;
        if (_currentPlayable && self.player.currentItem) {
            CVPixelBufferRef buff = [self.videoOutput copyPixelBufferForItemTime:self.player.currentItem.currentTime itemTimeForDisplay:nil];
            CGImageRef cgImage = NULL;
            VTCreateCGImageFromCVPixelBuffer(buff, NULL, &cgImage);
            UIImage *image = nil;
            if (cgImage != NULL) {
                image = [UIImage imageWithCGImage:cgImage];
                CGImageRelease(cgImage);
            }
            [_currentPlayable stopPlayWithCurrentImage:image];
        }
       
        [self.player pause];
        _currentPlayable = currentPlayable;
    }
}

- (void)playWithPlayable:(id<GKPlayable>) playable
{
    if (!playable.playing) {
        self.currentPlayable = playable;
        playable.playing = YES;
        [self setupPlayerWithPlayable:playable];
    }
}

- (void)setupPlayerWithPlayable:(id<GKPlayable>) playable
{
    NSURL *URL = [KTVHTTPCache proxyURLWithOriginalURL:playable.videoURL];
    AVURLAsset *asset = [AVURLAsset assetWithURL:URL];
    NSArray *keys = @[@"playable"];
    NSLog(@"开始下载 %@", playable.videoURL);
    [asset loadValuesAsynchronouslyForKeys:keys completionHandler:^() {
        [self onLoadAsset:asset playable:playable];
    }];
}


- (void)onLoadAsset:(AVURLAsset*) asset playable:(id<GKPlayable>) playable
{
    AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset];
    dispatch_async(dispatch_get_main_queue(), ^{
        if (playable == self.currentPlayable) {
            @try {
                NSLog(@"开始替换 %@", playable.videoURL);
                
                self.videoOutput = [[AVPlayerItemVideoOutput alloc] initWithOutputSettings:@{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)}];
                [item addOutput:self.videoOutput];
                [self.player replaceCurrentItemWithPlayerItem:item];
                [self.player play];
                [playable startPlayWithPlayer:self.player];
                [[NSNotificationCenter defaultCenter] addObserver:self
                                                           selector:@selector(playerItemDidReachEnd:)
                                                               name:AVPlayerItemDidPlayToEndTimeNotification
                                                             object:item];
            } @catch (NSException *exception) {
                NSLog(@"replaceCurrentItemWithPlayerItem exception %@", exception);
            }
        }
    });
}

// MARK: - 播放操作

- (void)play
{
    if (self.currentPlayable) {
        if (self.player.status == AVPlayerStatusReadyToPlay) {
            [self playAfterDelay:0.5];
        }
    }
}

- (void)playAfterDelay:(NSTimeInterval) delay
{
    [self performSelector:@selector(playAfterReady) withObject:nil afterDelay:delay];
}

- (void)playAfterReady
{
    [self.class cancelPreviousPerformRequestsWithTarget:self];
    if (self.currentPlayable.playing) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            [self.player play];
        });
    }
}

- (void)stop
{
    [self.class cancelPreviousPerformRequestsWithTarget:self];
    [NSNotificationCenter.defaultCenter removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
    [self.player pause];
}

//- (void)pause
//{
//    [self.class cancelPreviousPerformRequestsWithTarget:self];
//    if (!self.pausing && self.playing) {
//        self.pausing = YES;
//        [self.player pause];
//    }
//}
//
//- (void)resume
//{
//    [self.class cancelPreviousPerformRequestsWithTarget:self];
//    if (self.pausing && self.playing) {
//        self.pausing = NO;
//        [self.player play];
//    }
//}

// MARK: - 通知

//播放结束了
- (void)playerItemDidReachEnd:(NSNotification*) notification
{
    if (notification.object == self.player.currentItem) {
        [self.player seekToTime:kCMTimeZero];
        [self.player play];
    }
}

- (void)applicationWillResignActive:(NSNotification*) notification
{
//    [self pause];
}

- (void)applicationDidBecomeActive:(NSNotification*) notification
{
//    [self resume];
}

// MARK: - KVO

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (object == self.player && [keyPath isEqualToString:@"status"]) {
        if (self.player.status == AVPlayerStatusReadyToPlay) {
            NSLog(@"准备播放");
//            [self playAfterDelay:0.5];
        }
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

- (void)dealloc
{
    [self stop];
    [self.player removeObserver:self forKeyPath:@"status"];
    [NSNotificationCenter.defaultCenter removeObserver:self];
}

@end
